//此go文件为重要逻辑文件,如需增加新的model,
//需要在下方 ModeType 增加常量,
//需要在下方 ModelToRegister 增加注册模型.
// ModelToRegister 用来自动迁移模型和注册模型接口,可获得一个 NewModelCRUD 的接口;用来进行调用 models 中的CURD.
//
//***** 如需增加 model（数据库表）那么必须要增加 CRUD 接口中的方法. *****

package models

import (
	"io"
	"os"
	"regexp"
	"strings"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/schema"

	loggers "huijing_mall/pkg/logger"
)

// BaseModel 基础model
type BaseModel struct {
	ID        uint           `gorm:"primaryKey" json:"id"`
	CreatedAt time.Time      `gorm:"autoCreateTime" json:"created_at"`
	UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"updated_at"`
	DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
}

// ModelType 定义model类型常量，便于工厂函数识别
type ModelType string

const (
	UserType              ModelType = "user"
	UserAvatarHistoryType ModelType = "user_avatar_history"
	UserAddressType       ModelType = "user_address"
	RoleType              ModelType = "Role"
	PermissionType        ModelType = "permission"
	UserRoleType          ModelType = "user_role"
	RolePermissionType    ModelType = "role_permission"
	ProductType           ModelType = "product"
	ProductCategoryType   ModelType = "product_category"
	ProductSpecType       ModelType = "product_spec"
	BossType              ModelType = "boss"
	TaskType              ModelType = "task"
	TaskKeyType           ModelType = "task_key"
	AreaType              ModelType = "Area"
	OrderType             ModelType = "order"
	CartType              ModelType = "cart"
	CouponType            ModelType = "coupon"
	InventoryLogType      ModelType = "inventory_log"
	// 新增其他model类型...
)

// 模型注册信息（共享数据源）
var ModelToRegister = []struct {
	Type    ModelType
	Creator modelCreator // 函数：返回模型实例（如 &User{}）
}{
	{UserType, func() ModelCRUD { return &User{} }},
	{UserAvatarHistoryType, func() ModelCRUD { return &UserAvatarHistory{} }},
	{UserAddressType, func() ModelCRUD { return &UserAddress{} }},
	//{RoleType, func() ModelCRUD { return &Role{} }},
	//{PermissionType, func() ModelCRUD { return &Permission{} }},
	//{UserRoleType, func() ModelCRUD { return &UserRole{} }},
	//{RolePermissionType, func() ModelCRUD { return &RolePermission{} }},
	{ProductType, func() ModelCRUD { return &Product{} }},
	{ProductCategoryType, func() ModelCRUD { return &ProductCategory{} }},
	{ProductSpecType, func() ModelCRUD { return &ProductSpec{} }},
	{BossType, func() ModelCRUD { return &Boss{} }},
	{TaskType, func() ModelCRUD { return &Task{} }},
	{TaskKeyType, func() ModelCRUD { return &TaskKey{} }},
	{AreaType, func() ModelCRUD { return &Area{} }},
	{OrderType, func() ModelCRUD { return &Order{} }},
	{CouponType, func() ModelCRUD { return &Coupon{} }},
	{InventoryLogType, func() ModelCRUD { return &InventoryLog{} }},
	{CartType, func() ModelCRUD { return &Cart{} }},
	// Order 模型（新增模型只需在这里加一条）
}

// 定义驼峰转下划线的函数
var camelRegex = regexp.MustCompile(`([a-z0-9])([A-Z])`)

func camelToSnake(camel string) string {
	// 将驼峰式（如InventoryLog）转为下划线式（inventory_log）
	snake := camelRegex.ReplaceAllString(camel, "${1}_${2}")
	return strings.ToLower(snake)
}

// 自定义NamingStrategy，实现自动转换
type CustomNamingStrategy struct {
	schema.NamingStrategy
}

// TableName 重写表名生成逻辑：自动驼峰转下划线
func (c CustomNamingStrategy) TableName(table string) string {
	// 如果全局配置了表名前缀，先加上前缀
	if c.TablePrefix != "" {
		table = c.TablePrefix + table
	}
	// 驼峰转下划线（核心逻辑）
	return camelToSnake(table)
}

func AutoCreateTable(name string, db *gorm.DB) {
	sqlFile, err := os.Open(name)
	if err != nil {
		loggers.Info("failed to open sql file")
	}
	defer sqlFile.Close()

	// 读取 SQL 文件内容
	sqlBytes, err := io.ReadAll(sqlFile)
	if err != nil {
		loggers.Info("failed to read sql file")
	}

	// 执行 SQL 文件中的语句
	sqlArr := strings.Split(string(sqlBytes), ";")
	for _, sql := range sqlArr {
		sql = strings.TrimSpace(sql)
		if sql == "" {
			continue
		}
		errs := db.Exec(sql).Error
		if errs != nil {
			loggers.Info("数据库导入失败:" + errs.Error())
			return
		}
	}
}
